import { getSceneByName } from '../../components/three/ThreeScene.vue'
import * as THREE from 'three'
import * as Cesium from 'cesium'
import { on, THREE_SCENE_INITIALIZATION } from '../../utils/EventBus.js'
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js'
import { loadGltf } from './LoadGltf.js'
import { ModelUtils } from '../../components/cesium-three/ModelUtils.js'
// import { getDirectionalLight } from '../../components/three/light/DirectionalLight.js'
import { getSunLightDirectionn } from '../../components/cesium-three/sun.js'

import { waitUntilValueExist } from '../../utils/unsorted.js'
import { SyncCesiumWithThree } from '../../components/cesium-three/SyncCesiumWithThree.js'

// import {mapControls} from './controls.js'
import { RapierPhysics, MyCharacterController } from './rapier/RapierPhysics.js'
import { MapControls } from 'three/addons/controls/MapControls.js'
import { fp2 } from './fp2.js'
export const group = new THREE.Group()

export const sceneName = 'threeScene'
import {
    fp,
    velocity,
    updateVelocityFromInput,
    animate,
} from './first-person.js'

const _vector = new THREE.Vector3()
function getNewForward(camera, distance) {
    _vector.setFromMatrixColumn(camera.matrix, 0)

    _vector.crossVectors(camera.up, _vector)

    return (
        new THREE.Vector3()
            // .copy(camera.position)
            .addScaledVector(_vector, distance)
    )
}

function getNewRight(camera, distance) {
    _vector.setFromMatrixColumn(camera.matrix, 0)
    return (
        new THREE.Vector3()
            // .copy(camera.position)
            .addScaledVector(_vector, distance)
    )
}

on(THREE_SCENE_INITIALIZATION, async ({ detail: { sceneName: t3Name } }) => {
    if (sceneName !== t3Name) return

    const scene = getSceneByName(sceneName)

    const physics = await RapierPhysics()
    const { RAPIER } = physics
    const mcc = new MyCharacterController(RAPIER, physics.world)

    // fp()

    const { renderer, camera, preRender, postRender } = scene.my
    camera.position.set(120, 120, 120)

    new MapControls(camera, renderer.domElement)

    {
        const ground = new THREE.Mesh(
            new THREE.BoxGeometry(500, 300, 0.2),
            // new THREE.MeshPhongMaterial({ color: 0xa0adaf, shininess: 150 })
            new THREE.MeshStandardMaterial({
                color: 0x666666,
                shininess: 0,
            })
        )
        ground.userData.physics = { mass: 0, restitution: 0 }
        ground.rotation.x = -Math.PI / 2 // rotates X/Y to X/Z
        ground.position.set(0, -0.5, 0)
        ground.receiveShadow = true
        scene.add(ground)
        // physics.addScene(ground)
    }

    const axesHelper = new THREE.AxesHelper(500)

    // group.add(axesHelper)

    // scene.add(group)
    // scene.add(axesHelper)

    loadRGBE()
    function loadRGBE() {
        new RGBELoader()
            .setPath('/equirectangular/')
            .load('royal_esplanade_1k.hdr', function (texture) {
                texture.mapping = THREE.EquirectangularReflectionMapping

                scene.background = new THREE.Color(0x000000)
                scene.environment = texture
            })
    }

    const { controls, playerVelocity, getWill, reset } = fp2()

    // loadGltf('ramps.glb', scene)
    loadGltf('tank.glb', scene)
        .then((model) => {
            console.log('🚀 ~ .then ~ model:', model)
            model.traverse((child) => {
                if (child.isMesh) {
                    child.userData.physics = {
                        mass: 0,
                        restitution: 1.0,
                    }
                }
            })
            const g1 = moveToOrigin(model)
            scene.add(g1)
        })
        .then(() => {
            physics.addScene(scene)

            // fp2
            const physicsStep = (delta) => {
                const isGrounded = mcc.characterController.computedGrounded()

                if (!isGrounded) {
                    console.log('🚀 ~ physicsStep ~ isGrounded:', isGrounded)
                }
                delta = delta * 1.0
                // delta = Math.min(0.05, delta) // STEPS_PER_FRAME
                controls(delta, isGrounded)
                const tr = getWill(delta, isGrounded)

                mcc.testCollision(tr, (pos) => {
                    camera.position.x = pos.x
                    camera.position.y = pos.y
                    camera.position.z = pos.z
                })
            }

            on('collision', ({ detail }) => {
                if (detail) {
                    // lock()
                    preRender.push(physicsStep)
                } else {
                    preRender.splice(preRender.indexOf(physicsStep), 1)
                }
            })
        })

    /*
  function beginRotate(radius) {
    return (angle) => {
      angle /= 5000
      // const radius = 10 // 调整旋转半径
      camera.position.x = radius * Math.sin(angle)
      camera.position.z = radius * Math.cos(angle)
      camera.lookAt(0, 0, 0) // 确保相机始终看向目标点

      // renderer.render(scene, camera)
    }
  }

    */
    function moveToOrigin(object) {
        // Create a bounding box for the object
        const boundingBox = new THREE.Box3().setFromObject(object)

        // // Calculate the center of the bounding box
        const center = boundingBox.getCenter(new THREE.Vector3())
        center.y = boundingBox.min.y

        // Create a group to hold the model
        const group = new THREE.Group()
        group.aabb = boundingBox

        // Add the model to the group
        group.add(object)
        window.threeScene.tempCenter = center

        console.log('🚀 ~ moveToOrigin ~ center:', center)
        // Move the group so the model's center is at the origin
        group.position.sub(center)

        return group
    }
})

/*
            fp1
            const physicsStep = () => {


                const z = velocity.z * velocity.delta
                const x = velocity.x * velocity.delta
                console.log(mcc.characterController.computedGrounded())

                // animate(mcc)

                // const z = velocity.z
                // const x = velocity.x

                const { RAPIER } = physics

                const r1 = getNewForward(camera, z)
                const r2 = getNewRight(camera, x)
                r1.add(r2)
                r1.negate()
                r1.y = velocity.y * velocity.delta

                mcc.testCollision(r1, (pos) => {
                    // console.log("🚀 ~ mcc.testCollision ~ pos:", pos.y)
                    camera.position.x = pos.x
                    camera.position.y = pos.y
                    camera.position.z = pos.z
                })
            }
                */
